package websocket.service.impl;

import java.io.IOException;
import java.util.List;

import org.apache.log4j.Logger;

import websocket.constant.Status;
import websocket.pojo.Message;
import websocket.pojo.Users;
import websocket.service.BaseMsgHandleService;
import websocket.socket.MyWebSocket;
import websocket.socket.SocketContext;
import websocket.util.CommonUtil;

public class SysMsgHandleServiceImpl implements BaseMsgHandleService {
	private static final Logger logger = Logger
			.getLogger(SysMsgHandleServiceImpl.class.getName());
	private UserService service = new UserService();

	@Override
	public void handle(Message message, MyWebSocket socket) {
		switch (message.getStatus()) {
		case Status.SYS_ONLINE:
			if (SocketContext.getInstance().isExist(message.getFrom())) {// 如果该帐号之前已经登录
				this.sendMsg(new Message(Status.SYS_OTHERSPACE, 0L, message
						.getFrom(), message.getTime(), "OTHERSPACE"));
				MyWebSocket sc = SocketContext.getInstance().removeClient(
						message.getFrom());
				new KillSocketThread(sc).start();
				SocketContext.getInstance()
						.addClient(message.getFrom(), socket);
				socket.setUid(message.getFrom());
				break;
			}
			SocketContext.getInstance().addClient(message.getFrom(), socket);
			service.updateStatus(message.getFrom(),
					CommonUtil.transformStatus(message.getMsg()));// 更新状态
			socket.setUid(message.getFrom());
			this.noticeStatus(message, Status.USER_ONLINE);// 应该将上线的消息发送给自己的好友
			break;
		case Status.SYS_OFFLINE:
			MyWebSocket sc = SocketContext.getInstance().getSocket(
					message.getFrom());
			if (sc != null && sc.equals(socket)) {// 解决一个帐号多地登录时，KILL其中的出现多个被同时KILL掉的问题
				SocketContext.getInstance().removeClient(message.getFrom());
			}
			service.updateStatus(message.getFrom(), 0);
			this.noticeStatus(message, Status.USER_OFFLINE);// 应该将下线的消息发送给自己的好友
			break;
		case Status.SYS_BUSY:
			this.noticeStatus(message, Status.USER_BUSY);
			service.updateStatus(message.getFrom(), 2);
			break;
		case Status.SYS_AWAY:
			this.noticeStatus(message, Status.USER_AWAY);
			service.updateStatus(message.getFrom(), 3);
			break;
		case Status.SYS_INVISIBLE:
			service.updateStatus(message.getFrom(), 4);
			this.noticeStatus(message, Status.USER_OFFLINE);
			break;
		case Status.SYS_REONLINE:
			this.noticeStatus(message, Status.USER_ONLINE);
			service.updateStatus(message.getFrom(), 1);
			break;
		default:
			break;
		}
	}

	public void noticeStatus(Message message, int status) {
		List<Users> friends = new UserService().getOnlineFriends(message
				.getFrom());
		if (friends != null) {
			for (Users user : friends) {
				this.sendMsg(new Message(status, 0L, user.getUid(), message
						.getTime(), message.getFrom() + ""));
			}
		}
	}

	/**
	 * 发送消息
	 * 
	 * @param message
	 *            发送的消息实体类
	 */
	@Override
	public void sendMsg(Message message) {
		MyWebSocket socket = SocketContext.getInstance().getSocket(
				message.getTarget());
		try {
			if (socket != null && socket.getConn().isOpen()) {
				socket.getConn().sendMessage(
						CommonUtil.handleMsgToJSON(message));
			} else {
				// TODO 说明好友不在线，那么将会把这个消息转入离线消息
			}
		} catch (IOException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
	}

	/**
	 * 子类，负责关闭同一个帐号，在两个地方登录时，将前一个登录的给kill掉
	 * 
	 * @author zhc
	 * 
	 */
	class KillSocketThread extends Thread {
		private MyWebSocket socket;

		public KillSocketThread(MyWebSocket socket) {
			this.socket = socket;
		}

		@Override
		public void run() {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				logger.error(e.getMessage());
			} finally {// 无论如何也要关闭连接
				socket.getConn().close();
				socket = null;
			}
		}
	}
}
